﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using VisualWip.Core;
using VisualWip.Core.Columns;
using VisualWip.Core.Interfaces;
using VisualWip.Core.Utils;

namespace VisualWip.PresentationModel
{
    public abstract class SettingsViewModelBase<TColumn> : ISettingsViewModel, INotifyPropertyChanged
        where TColumn : ColumnBase
    {
        protected readonly TColumn Column;
        private ReadOnlyCollection<WindowNameViewModel> _windows;

        protected SettingsViewModelBase(Application application, TColumn column, IColumnTypeProvider columnTypeProvider)
        {
            Column = column;
            Attach(application, column);
            Column.PropertyChanged += ColumnPropertyChanged;
            ColumnTypes = new ObservableCollection<ColumnType>(columnTypeProvider.GetColumnTypes());
            if (Column.ColumnType == null)
                ColumnType = ColumnTypes.First();
        }

        public ColumnType ColumnType
        {
            get { return Column.ColumnType; }
            set { Column.ColumnType = value; }
        }

        public ObservableCollection<ColumnType> ColumnTypes { get; private set; }

        public bool ShowBorder
        {
            get { return Column.ShowBorder; }
            set { Column.ShowBorder = value; }
        }

        public bool ShowHeader
        {
            get { return Column.ShowHeader; }
            set { Column.ShowHeader = value; }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region ISettingsViewModel Members

        public abstract string SettingsWindowName { get; }

        public string ColumnName
        {
            get { return Column.ColumnName; }
            set { Column.ColumnName = value; }
        }


        public ReadOnlyCollection<WindowNameViewModel> Windows
        {
            get { return _windows; }
        }

        public WindowNameViewModel SelectedWindow
        {
            get
            {
                WindowNameViewModel windowNameViewModel =
                    Windows.FirstOrDefault(x => x.Window.WindowName == Column.WindowName);
                return windowNameViewModel;
            }
            set
            {
                Column.WindowName = value.Window.WindowName;
                OnPropertyChanged(this, () => SelectedWindow);
            }
        }

        #endregion


        private void Attach(Application application, TColumn column)
        {
            List<WindowNameViewModel> result =
                application.Windows.Select(window => new WindowNameViewModel(window)).ToList();
            _windows = new ReadOnlyCollection<WindowNameViewModel>(result);

            SelectedWindow = _windows.FirstOrDefault(x => x.WindowName == column.WindowName) ?? Windows.First();
        }

        protected virtual void ColumnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            BubbleOnPropertyChanged(e, () => ColumnName);
            BubbleOnPropertyChanged(e, () => ShowHeader);
            BubbleOnPropertyChanged(e, () => ShowBorder);
            BubbleOnPropertyChanged(e, () => ColumnType);
        }

        protected void BubbleOnPropertyChanged<T>(PropertyChangedEventArgs propertyChangedEventArgs,
                                                  Expression<Func<T>> property)
        {
            if (propertyChangedEventArgs.PropertyName == PropertyHelper.Name(property))
            {
                OnPropertyChanged(this, property);
            }
        }

        protected void OnPropertyChanged<T>(object sender, Expression<Func<T>> property)
        {
            PropertyHelper.OnPropertyChanged(sender, PropertyChanged, property);
        }
    }
}